/*
 * Application code begins here.
 */
# include <gtk/gtk.h>

typedef struct _typProgressData {
	GtkWidget *progressbar;
	GtkWidget *window;
	int bProgressUp;
	int nLastPct;
} typProgressData;
	typProgressData *pdata;
	int nValue;
	int ptimer;
	
/*
 * CanWindowClose
 *
 * Function that determines that if the dialog window can be closed.
 */
gint CanWindowClose (GtkWidget *widget)
{
	/* --- TRUE = > cannot close --- */
	/* --- FALSE = > can close --- */
	return (pdata->bProgressUp);
}

/*
 * StartProgress
 *
 * Create a window for the progress bar
 */
void StartProgress ()
{
	GtkWidget *label;
	GtkWidget *grid;
	GtkWidget *window;
	
	pdata = g_malloc (sizeof (typProgressData));
	pdata->nLastPct = -1;
	pdata->bProgressUp = TRUE;
	/*
	 * --- Create the top-level widow
	 */
	window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
	pdata->window = window;

	/* --- Hook up the destroy --- */
	g_signal_connect (G_OBJECT (window), "delete_event", G_CALLBACK (CanWindowClose), pdata);
	gtk_container_set_border_width (GTK_CONTAINER (window), 100);
	
	/* --- Create a grid --- */
	grid = gtk_grid_new ();
	gtk_container_add (GTK_CONTAINER (window), grid);

	/* --- Add a label to the grid --- */
	label = gtk_label_new ("Loading...");
	gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
	gtk_widget_show (label);

	/* --- Add the progress bar to the grid --- */
	pdata->progressbar = gtk_progress_bar_new ();
	gtk_grid_attach (GTK_GRID (grid), pdata->progressbar, 0, 1, 1, 1);
	gtk_widget_show (pdata->progressbar);

	/* --- Show everything --- */
	gtk_widget_show (grid);
	gtk_widget_show (window);
}

/*
 * UpdateProgress
 *
 * Update the progress window to reflect the state of the file that is being loaded.
 * 
 * pos - how much of the file has been loaded
 * len - length of the file
 * (pos/len) = % file has been loaded
 */
void UpdateProgress (long pos, long len)
{
	gfloat pvalue;
	int pct;
	/* --- Prevent divide by zero errors --- */
	if (len > 0)
	{
		/* --- Calculate the percentage --- */
		pvalue = (gfloat) pos / (gfloat) len;
		pct = pvalue * 100;
		if (pdata->nLastPct != pct)
		{
			/* --- Update the displayed value --- */
			gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pdata->progressbar), pvalue);
			/* --- Repaint any windows - like the progress bar --- */
			while (gtk_events_pending())
			{
				gtk_main_iteration ();
			}
			pdata->nLastPct = pct;
		}
	}
}

/*
 * EndProgress
 *
 * Close down the progress bar
 */
void EndProgress ()
{
	/* --- Allow it to close --- */
	pdata->bProgressUp = FALSE;

	/* --- Destroy the window --- */
	gtk_widget_destroy (pdata->window);

	/* --- Free used memory --- */
	g_free (pdata);
	pdata = NULL;
}

/*
 * UpdateProgressTimer
 * This is the timer callback function. It updates the progress bar and closes it when it reaches the end.
 */

gint UpdateProgressTimer (gpointer data)
{
	/* --- Increment value --- */
	nValue +=1;
	/* --- Update the progress bar --- */
	UpdateProgress (nValue, 100);
	/* --- Close if it's at the end. --- */
	if (nValue == 100)
	{
		EndProgress ();
		g_source_remove (ptimer);
	}
	return TRUE;
}

/* 
 * ButtonClicked
 *
 * Called to create the progress bar and the time when the button has been clicked.
 */
gint ButtonClicked (GtkWidget *widget, gpointer data)
{
	/* --- Do some initialization --- */
	nValue = 0;
	StartProgress ();
	/* --- Call the timer --- */
	ptimer = g_timeout_add (100, UpdateProgressTimer, data);
	return TRUE;
}

/* 
 * CloseAppWindow
 *
 * Close down the application
 */
gint CloseAppWindow ()
{
	gtk_main_quit ();
	return (FALSE);
}

/*
 * main
 *
 * program begins here
 */
int main (int argc, char *argv [])
{
	GtkWidget *window;
	GtkWidget *button;

	gtk_init (&argc, &argv);
	/* --- Create main window and give it a title --- */
	window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
	gtk_window_set_title (GTK_WINDOW (window), "Progress Bar");
	gtk_container_set_border_width (GTK_CONTAINER (window), 100);
	/* --- End app when close window detected --- */
	g_signal_connect (G_OBJECT (window), "delete_event", G_CALLBACK (CloseAppWindow), NULL);
	/* --- Create a button to bring up the progress bar --- */
	button = gtk_button_new_with_label ("Progress bar");
	gtk_widget_show (button);
	/* --- This is where we handle it --- */
	g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (ButtonClicked), NULL);
	gtk_container_add (GTK_CONTAINER (window), button);
	gtk_widget_show (window);

	/* --- Let GTK take over --- */
	gtk_main ();
	exit (0);
}

